/**
 * Event Bus
 * 事件总线
 *
 * @example
 * // 注册事件
 * $event.on('showComment', this, function(payload) {})
 *
 * // 触发事件
 * $event.emit('showCommit', { replyUser: 1 })
 *
 * // 注销事件
 * $event.off('showComment', this)
 */
export class EventBus {
  private events: WechatMiniprogram.IAnyObject = {}

  /**
   * 注册事件
   * @example
   * $event.on('showComment', this, function(payload) { console.log(payload) })
   */
  public on(eventName: string, self: Instance, handler: EventHandler): void {
    const cache = this.events[eventName] || (this.events[eventName] = {})
    cache[self.is || self.__route__!] = handler
  }

  /**
   * 注销事件
   * @example
   * $event.off('showComment', this)
   */
  public off(eventName: string, self: Instance): void {
    const path = self.is || self.__route__!
    const cache = this.events[eventName]
    for (const key in cache) {
      if (key === path) {
        delete this.events[eventName]
      }
    }
  }

  /**
   * 触发事件
   * @example
   * $event.emit('showCommit', { replyUser: 1 })
   */
  public emit(eventName: string, payload?: unknown): void {
    const cache = this.events[eventName]
    if (!cache) {
      return
    }
    for (const key in cache) {
      if (Object.prototype.hasOwnProperty.call(cache, key)) {
        cache[key].call(this, payload)
      }
    }
  }
}

/** 事件处理函数 */
type EventHandler = (...rest: any) => void

type Instance = (WechatMiniprogram.Page.Instance<any, any> | {}) & {
  /** 页面路由(组件) */
  is?: string
  /** 页面路由(页面) */
  __route__?: string
}
